#ifndef __BASE_PROTOCOL_H__
#define __BASE_PROTOCOL_H__

#include <memory>
#include <session.h>

#define DBNAME_MYSQL        "MYSQL"
#define DBNAME_MARIADB      "MARIADB"
#define DBNAME_TIDB         "TIDB"
#define DBNAME_SQLSERVER    "SQLSERVER"
#define DBNAME_SYBASE       "SYBASE"
#define DBNAME_GBASE8A      "GBASE8A"
#define DBNAME_ORACLE       "ORACLE"
#define DBNAME_POSTGRE      "POSTGRE"
#define DBNAME_TBASE        "TBASE"
#define DBNAME_VERTICA      "VERTICA"
#define DBNAME_GREENPLUM    "GREENPLUM"       
#define DBNAME_DAMENG       "DAMENG"            //达梦6,达梦7,8虽然协议略有不同，但数据库名统一输出DAMENG



namespace secsmart_protocol
{
    enum DETECT_RESULT { 
        DETECT_INIT,
        DETECT_OK,
        DETECT_UNKNOWN,
        DETECT_FAIL
    };

   

    class BaseProtocol{
    public:
        //解析数据包
        virtual DETECT_RESULT parse(secsmart_session::session_sptr session, const uint8_t *buf, size_t size, bool is_forward) = 0; 
        std::string getDatabaseName(){
            return databaseName;
        };
        std::string getVersion(){
            return version;
        };
       
        uint32_t getMatchCount(){
            return matchCount;
        }
        uint32_t getNoMatchCount(){
            return nomatchCount;
        }

        std::string getAssetIP(){
            return asset_ip;
        };
        uint16_t getAssetPort(){
            return asset_port;
        }
        //parse_forward:解析中识别出来的方向;  data_forward:网络层的数据包方向
        bool setIpPort(secsmart_session::session_sptr session,bool parse_forward,bool data_forward);
        
        virtual std::string extendInfo() = 0;
    protected:
        bool getDirction(){
            if(direction == secsmart_session::session_dirction_t::SESSION_DIRCTION_REQUEST){
                return true;
            }
            return false;
        }
        void addMatchCount(){
            ++matchCount;
            nomatchCount = 0;//有匹配上了，没有匹配上从头开始计数
        }
        void addNoMatchCount(){
            ++nomatchCount;
        }

       //以下几个函数均为读取数据包内容的辅助函数
        void skipBytesWithLen4(const uint8_t *buf, size_t &position,  size_t size);
        uint32_t readU32LE(const uint8_t *buf, size_t &position, size_t size);
        void skipLen(size_t &position, uint32_t Len);
        void readData(const uint8_t *buf, size_t &position, size_t size,std::string &str, uint32_t wantLen);
        void readBytesWithLen4(const uint8_t *buf, size_t &position, size_t size,std::string &str);


    protected:
        //记录当前包中的方向(正确)
        secsmart_session::session_dirction_t  direction = secsmart_session::session_dirction_t::SESSION_DIRCTION_UNKNOW;
      
        std::string databaseName = ""; //数据库名称信息
        std::string version = ""; //数据库版本信息
        std::string asset_ip = ""; //资产IP
        uint16_t asset_port = 0; //资产端口

    private:
        uint32_t matchCount = 0; //匹配成功包个数(不允许子类直接修改,调用相关方法)
        uint32_t nomatchCount = 0; //没有匹配成功包个数(不允许子类直接修改,调用相关方法)
    };
};

#endif